package cn.shujuhai.common.service.impl;

import cn.shujuhai.common.domain.SysMenu;
import cn.shujuhai.common.domain.SysPermissionMenu;
import cn.shujuhai.common.mapper.SysMenuMapper;
import cn.shujuhai.common.pluging.data.ResultCode;
import cn.shujuhai.common.pluging.data.ResultVo;
import cn.shujuhai.common.service.SysMenuService;
import cn.shujuhai.common.service.SysPermissionMenuService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @author NiuYaHu
 * @description 针对表【sys_menu(菜单表)】的数据库操作Service实现
 * @createDate 2024-11-04 09:39:48
 */
@Service
@RequiredArgsConstructor
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu>
        implements SysMenuService {
    final SysPermissionMenuService sysPermissionMenuService;

    /**
     * 获取菜单列表
     *
     * @return 排序后的菜单列表
     */
    @Override
    public ResultVo<List<SysMenu>> getMenuList() {
        List<SysMenu> sysMenus = this.list();
        List<SysMenu> sortedSysMenus = sysMenus.stream()
                .sorted(Comparator.comparingLong(SysMenu::getMenuSort))
                .collect(Collectors.toList());
        return ResultVo.success(sortedSysMenus);
    }

    /**
     * 菜单的启用禁用
     *
     * @param menuId 菜单Id
     * @return 成功或失败的结果及响应状态
     */
    @Override
    public ResultVo<SysMenu> enable(Long menuId) {
        SysMenu sysMenu = this.getById(menuId);
        if (sysMenu == null) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        // 切换状态，直接取反，0变1，1变0
        sysMenu.setStatus(sysMenu.getStatus() == 0 ? 1 : 0);
        // 更新菜单状态
        if (this.updateById(sysMenu)) {
            return ResultVo.success();
        } else {
            return ResultVo.failure(ResultCode.FAILED);
        }
    }

    /**
     * 根据菜单Id删除菜单
     *
     * @param menuId 菜单Id
     * @return 删除成功或失败的结果及响应信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<SysMenu> removeMenuById(Long menuId) {
        Set<Long> allMenuIds = getAllMenuIds(menuId);//获取当前菜单的所有子菜单
        allMenuIds.add(menuId); //将当前菜单添加到子菜单集合
        QueryWrapper<SysPermissionMenu> sysPermissionMenuQueryWrapper = new QueryWrapper<>();
        sysPermissionMenuQueryWrapper.lambda().in(SysPermissionMenu::getMenuId, allMenuIds);
        this.sysPermissionMenuService.remove(sysPermissionMenuQueryWrapper);
        if (!this.removeByIds(allMenuIds)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        return ResultVo.success();
    }

    /**
     * 递归查询一个菜单下的所有子菜单
     *
     * @param menuId 菜单id
     * @return 子菜单集合
     */
    public Set<Long> getAllMenuIds(Long menuId) {
        Set<Long> menuIds = new HashSet<>();
        getAllMenuIdsRecursively(menuId, menuIds);
        return menuIds;
    }

    private void getAllMenuIdsRecursively(Long menuId, Set<Long> menuIds) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysMenu::getParentId, menuId);
        List<SysMenu> menus = this.list(queryWrapper);
        for (SysMenu menu : menus) {
            menuIds.add(menu.getMenuId());
            getAllMenuIdsRecursively(menu.getMenuId(), menuIds);
        }
    }

    /**
     * 新增菜单
     *
     * @param sysMenu 新增菜单对象
     * @return 新增菜单对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> addMenu(@Validated SysMenu sysMenu) {
        if (!this.list(Wrappers.<SysMenu>lambdaQuery().eq(SysMenu::getTitle, sysMenu.getTitle())).isEmpty()) {
            return ResultVo.failure(ResultCode.MENU_EXIST);
        }
        if (!this.save(sysMenu)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        List<SysPermissionMenu> permissionsToSave = new ArrayList<>();
        // 处理权限
        if (sysMenu.getPermissionIds() != null && !sysMenu.getPermissionIds().isEmpty()) {
            for (Long permissionId : sysMenu.getPermissionIds()) {
                SysPermissionMenu sysPermissionMenu = new SysPermissionMenu();
                sysPermissionMenu.setMenuId(sysMenu.getMenuId());
                sysPermissionMenu.setPermissionId(permissionId);
                permissionsToSave.add(sysPermissionMenu);
            }
            // 保存权限
            if (!this.sysPermissionMenuService.saveBatch(permissionsToSave)) {
                return ResultVo.failure(ResultCode.FAILED);
            }
        }
        return ResultVo.success(sysMenu);
    }

    /**
     * 根据菜单Id获取菜单
     *
     * @param menuId 菜单Id
     * @return 获取到的菜单对象
     */
    @Override
    public ResultVo<?> getMenuByMenuId(Long menuId) {
        return ResultVo.success(this.getById(menuId));
    }

    /**
     * 菜单编辑
     *
     * @param sysMenu 更新菜单对象
     * @return 更新后的菜单对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> updateMenu(@Validated SysMenu sysMenu) {
        if (!this.updateById(sysMenu)) {
            return ResultVo.failure(ResultCode.FAILED);
        } else {
            //删除菜单权限中间表的记录
            List<Long> permissionIds = this.getPermissionIdsByMenuId(sysMenu.getMenuId());
            if (!(sysMenu.getPermissionIds().equals(permissionIds))) { //判断编辑之后权限是否发生变化
                QueryWrapper<SysPermissionMenu> query = new QueryWrapper<>();
                query.lambda().eq(SysPermissionMenu::getMenuId, sysMenu.getMenuId());
                if (sysMenu.getPermissionIds().isEmpty()) {   //判断当前菜单权限是否为空
                    this.sysPermissionMenuService.remove(query);
                } else {
                    this.sysPermissionMenuService.remove(query);
                    List<SysPermissionMenu> permissionsToSave = new ArrayList<>();
                    for (Long permissionId : sysMenu.getPermissionIds()) {
                        SysPermissionMenu permission = new SysPermissionMenu();
                        permission.setMenuId(sysMenu.getMenuId());
                        permission.setPermissionId(permissionId);
                        permissionsToSave.add(permission);
                    }
                    if (!this.sysPermissionMenuService.saveBatch(permissionsToSave)) {
                        return ResultVo.failure(ResultCode.FAILED);
                    }
                }
            }
        }
        return ResultVo.success();
    }

    /**
     * 获取菜单列表，构建菜单树
     *
     * @param menuIds 菜单Id集合
     * @return 构建的菜单树
     */
    @Override
    public List<SysMenu> getList(List<Long> menuIds) {
        // 从数据库中一次性查询出所有菜单
        List<SysMenu> allMenu = this.listByIds(menuIds);
        List<SysMenu> sortedSysMenus = allMenu.stream()
                .sorted(Comparator.comparingLong(SysMenu::getMenuSort))
                .toList();
        // 使用Map来根据menuId快速查找菜单
        Map<Long, SysMenu> menuMap = new HashMap<>();
        for (SysMenu menu : sortedSysMenus) {
            menuMap.put(menu.getMenuId(), menu);
        }
        // 提取顶级菜单（parentId为0的菜单）
        List<SysMenu> topLevelMenu = sortedSysMenus.stream()
                .filter(menu -> menu.getParentId() == 0)
                .collect(Collectors.toList());
        // 返回构建菜单树
        return buildMenuTree(topLevelMenu, menuMap);
    }

    /**
     * 递归构建菜单树
     *
     * @param menus   顶级菜单
     * @param menuMap 菜单集合
     * @return 构建的菜单树
     */
    private List<SysMenu> buildMenuTree(List<SysMenu> menus, Map<Long, SysMenu> menuMap) {
        List<SysMenu> menuList = new ArrayList<>();
        for (SysMenu menu : menus) {
            SysMenu sysMenu = new SysMenu();
            BeanUtils.copyProperties(menu, sysMenu); //复制属性
            // 查找并排序子菜单
            List<SysMenu> childrenMenus = menuMap.values().stream()
                    .filter(child -> child.getParentId().equals(menu.getMenuId()))
                    .sorted(Comparator.comparingLong(SysMenu::getMenuSort))
                    .collect(Collectors.toList());
            // 递归构建子菜单树
            List<SysMenu> childrenVoList = buildMenuTree(childrenMenus, menuMap);
            sysMenu.setChildren(childrenVoList);
            menuList.add(sysMenu);
        }
        return menuList;
    }

    /**
     * 根据菜单Id获取权限Id
     *
     * @param menuId 菜单Id
     * @return 菜单对应的权限id集合
     */
    @Override
    public List<Long> getPermissionIdsByMenuId(Long menuId) {
        return this.sysPermissionMenuService.list(Wrappers.<SysPermissionMenu>lambdaQuery().eq(SysPermissionMenu::getMenuId, menuId))
                .stream()
                .map(SysPermissionMenu::getPermissionId)
                .toList();
    }
}





